<template>
  <div class="role-list">
    <div class="page-header">
      <div class="header-content">
        <h1>角色管理</h1>
        <p class="subtitle">管理系统角色和权限分配</p>
      </div>
      <div class="header-actions">
        <el-button type="primary" @click="handleAdd" class="action-btn">
          <el-icon><Plus /></el-icon>
          新增角色
        </el-button>
      </div>
    </div>

    <!-- 搜索区域 -->
    <el-card class="search-card" shadow="never">
      <div class="search-header">
        <el-icon><Search /></el-icon>
        <span>搜索筛选</span>
      </div>
      <el-form :model="searchForm" inline class="search-form">
        <el-form-item label="角色名称" class="form-item">
          <el-input 
            v-model="searchForm.name" 
            placeholder="请输入角色名称"
            clearable
            class="search-input"
          />
        </el-form-item>
        <el-form-item label="角色编码" class="form-item">
          <el-input 
            v-model="searchForm.code" 
            placeholder="请输入角色编码"
            clearable
            class="search-input"
          />
        </el-form-item>
        <el-form-item label="状态" class="form-item">
          <el-select v-model="searchForm.status" placeholder="请选择状态" clearable class="search-select">
            <el-option label="启用" value="1" />
            <el-option label="禁用" value="0" />
          </el-select>
        </el-form-item>
        <el-form-item class="form-item">
          <el-button type="primary" @click="handleSearch" class="search-btn">
            <el-icon><Search /></el-icon>
            搜索
          </el-button>
          <el-button @click="handleReset" class="reset-btn">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 角色表格 -->
    <el-card class="table-card" shadow="never">
      <div class="table-header">
        <div class="table-info">
          <span class="info-text">共 {{ filteredRoleList.length }} 条角色</span>
          <span v-if="selectedRoles.length > 0" class="selected-info">
            已选择 {{ selectedRoles.length }} 项
          </span>
        </div>
        <div class="table-actions">
          <el-button size="small" :disabled="selectedRoles.length === 0" @click="handleBatchDelete">
            批量删除
          </el-button>
        </div>
      </div>
      
      <div v-if="error" class="error-message">
        <el-icon><Warning /></el-icon>
        <span>{{ error }}</span>
      </div>
      
      <div v-if="loading" class="loading-container">
        <el-loading-spinner type="circle" size="large"></el-loading-spinner>
        <p>正在加载角色数据...</p>
      </div>
      
      <el-table 
        v-if="dataLoadSuccess" 
        :data="displayRoleList" 
        class="role-table"
        border
        stripe
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column type="index" label="序号" width="60" align="center">
          <template #default="scope">
            <span class="index-text">{{ (pagination.current - 1) * pagination.size + scope.$index + 1 }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="id" label="角色ID" width="80" align="center" />
        <el-table-column prop="name" label="角色名称" width="120" />
        <el-table-column prop="code" label="角色编码" width="120" />
        <el-table-column prop="description" label="角色描述" min-width="200" show-overflow-tooltip />
        <el-table-column label="权限数量" width="100" align="center">
          <template #default="scope">
            <el-tag type="info" size="small">{{ scope.row.permissions?.length || 0 }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="状态" width="80" align="center">
          <template #default="scope">
            <el-tag :type="scope.row.status === '1' ? 'success' : 'danger'" size="small">
              {{ scope.row.status === '1' ? '启用' : '禁用' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="createTime" label="创建时间" width="160" align="center">
          <template #default="scope">
            <span>{{ formatDateTime(scope.row.createTime) }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="200" align="center" fixed="right">
          <template #default="scope">
            <el-button size="small" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button size="small" type="primary" @click="handleAssignPermission(scope.row)">分配权限</el-button>
            <el-button 
              size="small" 
              :type="scope.row.status === '1' ? 'warning' : 'success'"
              @click="handleToggleStatus(scope.row)"
            >
              {{ scope.row.status === '1' ? '禁用' : '启用' }}
            </el-button>
            <el-button size="small" type="danger" @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <div class="pagination-container">
        <el-pagination
          v-model:current-page="pagination.current"
          v-model:page-size="pagination.size"
          :page-sizes="[10, 20, 50, 100]"
          :total="filteredRoleList.length"
          layout="total, sizes, prev, pager, next, jumper"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </el-card>

    <!-- 角色表单对话框 -->
    <el-dialog
      v-model="dialogVisible"
      :title="dialogTitle"
      width="600px"
      :close-on-click-modal="false"
      @close="handleDialogClose"
    >
      <el-form
        ref="roleFormRef"
        :model="roleForm"
        :rules="roleFormRules"
        label-width="100px"
        class="role-form"
      >
        <el-form-item label="角色名称" prop="name">
          <el-input v-model="roleForm.name" placeholder="请输入角色名称" />
        </el-form-item>
        <el-form-item label="角色编码" prop="code">
          <el-input v-model="roleForm.code" placeholder="请输入角色编码" :disabled="isEdit" />
        </el-form-item>
        <el-form-item label="角色描述" prop="description">
          <el-input v-model="roleForm.description" type="textarea" :rows="3" placeholder="请输入角色描述" />
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-radio-group v-model="roleForm.status">
            <el-radio label="1">启用</el-radio>
            <el-radio label="0">禁用</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="排序" prop="sort">
          <el-input-number v-model="roleForm.sort" :min="0" :max="999" placeholder="请输入排序值" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleSubmit" :loading="submitLoading">确定</el-button>
      </template>
    </el-dialog>

    <!-- 权限分配对话框 -->
    <el-dialog
      v-model="permissionDialogVisible"
      title="分配权限"
      width="800px"
      :close-on-click-modal="false"
    >
      <div class="permission-assignment">
        <p class="assignment-info">为角色 <strong>{{ currentRole?.name }}</strong> 分配权限：</p>
        <el-tree
          ref="permissionTreeRef"
          :data="permissionTreeData"
          :props="permissionTreeProps"
          show-checkbox
          node-key="id"
          :default-checked-keys="selectedPermissions"
          :default-expanded-keys="expandedKeys"
          class="permission-tree"
        >
          <template #default="{ node, data }">
            <span class="permission-node">
              <el-icon v-if="data.icon" class="permission-icon">
                <component :is="data.icon" />
              </el-icon>
              <span class="permission-label">{{ data.label }}</span>
              <span v-if="data.description" class="permission-description">{{ data.description }}</span>
            </span>
          </template>
        </el-tree>
      </div>
      <template #footer>
        <el-button @click="permissionDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handlePermissionSubmit" :loading="permissionSubmitLoading">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script>
import { defineComponent, ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { request } from '@/utils/request'
import { Plus, Search, Warning } from '@element-plus/icons-vue'
import dayjs from 'dayjs'

export default defineComponent({
  name: 'RoleList',
  components: {
    Plus,
    Search,
    Warning
  },
  setup() {
    // 响应式数据
    const loading = ref(false)
    const error = ref('')
    const dataLoadSuccess = ref(false)
    const dialogVisible = ref(false)
    const permissionDialogVisible = ref(false)
    const isEdit = ref(false)
    const submitLoading = ref(false)
    const permissionSubmitLoading = ref(false)
    const selectedRoles = ref([])
    const currentRole = ref(null)
    const selectedPermissions = ref([])
    const expandedKeys = ref([])
    const roleFormRef = ref(null)
    const permissionTreeRef = ref(null)

    // 角色列表数据
    const roleList = ref([])
    const permissionTreeData = ref([])

    // 搜索表单
    const searchForm = reactive({
      name: '',
      code: '',
      status: ''
    })

    // 角色表单
    const roleForm = reactive({
      id: '',
      name: '',
      code: '',
      description: '',
      status: '1',
      sort: 0
    })

    // 分页配置
    const pagination = reactive({
      current: 1,
      size: 20
    })

    // 权限树配置
    const permissionTreeProps = {
      children: 'children',
      label: 'label'
    }

    // 表单验证规则
    const roleFormRules = {
      name: [
        { required: true, message: '请输入角色名称', trigger: 'blur' },
        { min: 2, max: 50, message: '角色名称长度在 2 到 50 个字符', trigger: 'blur' }
      ],
      code: [
        { required: true, message: '请输入角色编码', trigger: 'blur' },
        { pattern: /^[A-Z_]+$/, message: '角色编码只能包含大写字母和下划线', trigger: 'blur' }
      ],
      description: [
        { max: 200, message: '角色描述不能超过 200 个字符', trigger: 'blur' }
      ]
    }

    // 计算属性
    const filteredRoleList = computed(() => {
      let filtered = roleList.value

      if (searchForm.name) {
        filtered = filtered.filter(role => 
          role.name.toLowerCase().includes(searchForm.name.toLowerCase())
        )
      }

      if (searchForm.code) {
        filtered = filtered.filter(role => 
          role.code.toLowerCase().includes(searchForm.code.toLowerCase())
        )
      }

      if (searchForm.status !== '') {
        filtered = filtered.filter(role => role.status === searchForm.status)
      }

      return filtered
    })

    const displayRoleList = computed(() => {
      const start = (pagination.current - 1) * pagination.size
      const end = start + pagination.size
      return filteredRoleList.value.slice(start, end)
    })

    const dialogTitle = computed(() => {
      return isEdit.value ? '编辑角色' : '新增角色'
    })

    // 方法
    const loadRoleList = async () => {
      loading.value = true
      error.value = ''
      
      try {
        const response = await request.get('/roles')
        roleList.value = response.data || []
        dataLoadSuccess.value = true
      } catch (err) {
        error.value = '加载角色数据失败'
        console.error('Load role list error:', err)
      } finally {
        loading.value = false
      }
    }

    const loadPermissionTree = async () => {
      try {
        const response = await request.get('/permissions/tree')
        permissionTreeData.value = response.data || []
        // 设置展开的节点
        expandedKeys.value = getExpandedKeys(permissionTreeData.value)
      } catch (err) {
        console.error('Load permission tree error:', err)
      }
    }

    const getExpandedKeys = (nodes) => {
      const keys = []
      const traverse = (nodeList) => {
        nodeList.forEach(node => {
          if (node.children && node.children.length > 0) {
            keys.push(node.id)
            traverse(node.children)
          }
        })
      }
      traverse(nodes)
      return keys
    }

    const handleSearch = () => {
      pagination.current = 1
    }

    const handleReset = () => {
      Object.keys(searchForm).forEach(key => {
        searchForm[key] = ''
      })
      pagination.current = 1
    }

    const handleAdd = () => {
      isEdit.value = false
      resetRoleForm()
      dialogVisible.value = true
    }

    const handleEdit = (row) => {
      isEdit.value = true
      Object.assign(roleForm, row)
      dialogVisible.value = true
    }

    const handleDelete = async (row) => {
      try {
        await ElMessageBox.confirm(
          `确定要删除角色 "${row.name}" 吗？`,
          '确认删除',
          {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }
        )

        await request.delete(`/roles/${row.id}`)
        ElMessage.success('删除成功')
        loadRoleList()
      } catch (err) {
        if (err !== 'cancel') {
          ElMessage.error('删除失败')
        }
      }
    }

    const handleToggleStatus = async (row) => {
      try {
        const newStatus = row.status === '1' ? '0' : '1'
        const statusText = newStatus === '1' ? '启用' : '禁用'
        
        await ElMessageBox.confirm(
          `确定要${statusText}角色 "${row.name}" 吗？`,
          '确认操作',
          {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }
        )

        await request.put(`/roles/${row.id}/status`, { status: newStatus })
        ElMessage.success(`${statusText}成功`)
        loadRoleList()
      } catch (err) {
        if (err !== 'cancel') {
          ElMessage.error('操作失败')
        }
      }
    }

    const handleAssignPermission = async (row) => {
      currentRole.value = row
      try {
        // 获取角色当前权限
        const response = await request.get(`/roles/${row.id}/permissions`)
        selectedPermissions.value = response.data || []
        permissionDialogVisible.value = true
      } catch (err) {
        ElMessage.error('获取角色权限失败')
      }
    }

    const handlePermissionSubmit = async () => {
      if (!permissionTreeRef.value) return
      
      permissionSubmitLoading.value = true
      
      try {
        const checkedKeys = permissionTreeRef.value.getCheckedKeys()
        const halfCheckedKeys = permissionTreeRef.value.getHalfCheckedKeys()
        const allKeys = [...checkedKeys, ...halfCheckedKeys]
        
        await request.put(`/roles/${currentRole.value.id}/permissions`, {
          permissionIds: allKeys
        })
        ElMessage.success('权限分配成功')
        permissionDialogVisible.value = false
        loadRoleList()
      } catch (err) {
        ElMessage.error('权限分配失败')
      } finally {
        permissionSubmitLoading.value = false
      }
    }

    const handleSubmit = async () => {
      if (!roleFormRef.value) return
      
      try {
        await roleFormRef.value.validate()
        submitLoading.value = true

        if (isEdit.value) {
          await request.put(`/roles/${roleForm.id}`, roleForm)
          ElMessage.success('更新成功')
        } else {
          await request.post('/roles', roleForm)
          ElMessage.success('创建成功')
        }

        dialogVisible.value = false
        loadRoleList()
      } catch (err) {
        if (err !== false) {
          ElMessage.error(isEdit.value ? '更新失败' : '创建失败')
        }
      } finally {
        submitLoading.value = false
      }
    }

    const handleDialogClose = () => {
      resetRoleForm()
      if (roleFormRef.value) {
        roleFormRef.value.resetFields()
      }
    }

    const resetRoleForm = () => {
      Object.assign(roleForm, {
        id: '',
        name: '',
        code: '',
        description: '',
        status: '1',
        sort: 0
      })
    }

    const handleSelectionChange = (selection) => {
      selectedRoles.value = selection
    }

    const handleBatchDelete = async () => {
      if (selectedRoles.value.length === 0) return

      try {
        await ElMessageBox.confirm(
          `确定要删除选中的 ${selectedRoles.value.length} 个角色吗？`,
          '确认删除',
          {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }
        )

        const ids = selectedRoles.value.map(role => role.id)
        await request.delete('/roles/batch', { data: { ids } })
        ElMessage.success('批量删除成功')
        loadRoleList()
      } catch (err) {
        if (err !== 'cancel') {
          ElMessage.error('批量删除失败')
        }
      }
    }

    const handleSizeChange = (size) => {
      pagination.size = size
      pagination.current = 1
    }

    const handleCurrentChange = (current) => {
      pagination.current = current
    }

    const formatDateTime = (dateTime) => {
      if (!dateTime) return '-'
      return dayjs(dateTime).format('YYYY-MM-DD HH:mm:ss')
    }

    // 生命周期
    onMounted(() => {
      loadRoleList()
      loadPermissionTree()
    })

    return {
      loading,
      error,
      dataLoadSuccess,
      dialogVisible,
      permissionDialogVisible,
      isEdit,
      submitLoading,
      permissionSubmitLoading,
      selectedRoles,
      currentRole,
      selectedPermissions,
      expandedKeys,
      roleFormRef,
      permissionTreeRef,
      roleList,
      permissionTreeData,
      permissionTreeProps,
      searchForm,
      roleForm,
      roleFormRules,
      pagination,
      filteredRoleList,
      displayRoleList,
      dialogTitle,
      handleSearch,
      handleReset,
      handleAdd,
      handleEdit,
      handleDelete,
      handleToggleStatus,
      handleAssignPermission,
      handlePermissionSubmit,
      handleSubmit,
      handleDialogClose,
      handleSelectionChange,
      handleBatchDelete,
      handleSizeChange,
      handleCurrentChange,
      formatDateTime
    }
  }
})
</script>

<style lang="scss" scoped>
@use '../../styles/variables.scss' as *;
@use '../../styles/responsive.scss' as *;
@use '../../styles/common.scss' as *;

.role-list {
  padding: 20px;
  
  @include respond-to(xs) {
    padding: 12px;
  }
}

.page-header {
  @include flex-between;
  margin-bottom: 20px;
  
  @include respond-to(xs) {
    flex-direction: column;
    gap: 12px;
    align-items: flex-start;
  }
  
  .header-content {
    h1 {
      margin: 0 0 4px 0;
      font-size: 24px;
      font-weight: 600;
      color: var(--text-color-primary);
    }
    
    .subtitle {
      margin: 0;
      color: var(--text-color-secondary);
      font-size: 14px;
    }
  }
  
  .header-actions {
    @include flex-center;
    gap: 8px;
    
    .action-btn {
      @include flex-center;
      gap: 4px;
    }
  }
}

.search-card {
  margin-bottom: 20px;
  
  .search-header {
    @include flex-center;
    gap: 8px;
    margin-bottom: 16px;
    font-weight: 500;
    color: var(--text-color-primary);
  }
  
  .search-form {
    .form-item {
      margin-bottom: 12px;
      
      .search-input,
      .search-select {
        width: 200px;
        
        @include respond-to(xs) {
          width: 100%;
        }
      }
    }
    
    .search-btn,
    .reset-btn {
      @include flex-center;
      gap: 4px;
    }
  }
}

.table-card {
  .table-header {
    @include flex-between;
    margin-bottom: 16px;
    
    .table-info {
      @include flex-center;
      gap: 12px;
      
      .info-text {
        color: var(--text-color-secondary);
        font-size: 14px;
      }
      
      .selected-info {
        color: var(--primary-color);
        font-size: 14px;
        font-weight: 500;
      }
    }
  }
  
  .error-message {
    @include flex-center;
    gap: 8px;
    padding: 20px;
    color: var(--danger-color);
    background: var(--danger-bg);
    border-radius: 4px;
    margin-bottom: 16px;
  }
  
  .loading-container {
    @include flex-center;
    flex-direction: column;
    gap: 12px;
    padding: 40px;
    color: var(--text-color-secondary);
  }
}

.role-table {
  .index-text {
    color: var(--text-color-secondary);
    font-size: 13px;
  }
}

.pagination-container {
  @include flex-center;
  margin-top: 20px;
}

.role-form {
  .el-form-item {
    margin-bottom: 20px;
  }
}

.permission-assignment {
  .assignment-info {
    margin-bottom: 16px;
    color: var(--text-color-primary);
  }
  
  .permission-tree {
    max-height: 400px;
    overflow-y: auto;
    border: 1px solid var(--border-color);
    border-radius: 4px;
    padding: 12px;
    
    .permission-node {
      display: flex;
      align-items: center;
      gap: 8px;
      
      .permission-icon {
        color: var(--text-color-secondary);
        font-size: 14px;
      }
      
      .permission-label {
        font-weight: 500;
        color: var(--text-color-primary);
      }
      
      .permission-description {
        color: var(--text-color-secondary);
        font-size: 12px;
        margin-left: 8px;
      }
    }
  }
}
</style> 